<?php
namespace Swiftx\Component\Orm\Reflection;
use ReflectionProperty;
use Swiftx\Component\Orm\Exceptions\Error;

/**
 * 属性抽象
 * @package Swiftx\Component\Orm\Reflection
 */
class Property {

    /**
     * 所属 Schema 对象
     * @var Schema
     */
    protected $schema;

    /**
     * 属性映射的列名
     * @var string
     */
    protected $column;

    /**
     * 属性反射对象
     * @var ReflectionProperty
     */
    protected $property;

    /**
     * 是否是ORM属性
     * @var bool
     */
    protected $isSupport;

    /**
     * 字段类型
     * @var string
     */
    protected $type;

    /**
     * 约束集合
     * @var string[]
     */
    protected $constraint = [];

    /**
     * 默认值
     * @var string
     */
    protected $default = null;

    /**
     * 字段注释
     * @var string
     */
    protected $comment = null;

    /**
     * 生成属性对象
     * @param Schema $schema
     * @param ReflectionProperty $property
     * @throws Error
     */
    public function __construct(Schema $schema, ReflectionProperty $property){
        $this->schema = $schema;
        $this->property = $property;
        $doc = $this->property->getDocComment();
        $params = [];
        $pattern = '/@orm\s+([^\s]+)\s+([^\s]+)\s+/';
        $this->isSupport = preg_match_all($pattern, $doc, $params)?true:false;
        if(!$this->isSupport) return;
        foreach ($params[1] as $key => $value) {
            $method = 'parseAnnotation'.ucfirst($value);
            if(!method_exists($this, $method))
                throw new Error('无法识别的注解:'.$property->class.'->'.$property->name.'::'.$value);
            call_user_func([$this, $method], $params[2][$key]);
        }
    }

    /**
     * 解析类型注解
     * @param string $value
     */
    protected function parseAnnotationColumn(string $value){
        $this->column = $value;
    }

    /**
     * 解析类型注解
     * @param string $value
     */
    protected function parseAnnotationType(string $value){
        $this->type = $value;
    }

    /**
     * 解析约束注解
     * @param string $value
     */
    protected function parseAnnotationConstraint(string $value){
        $this->constraint[$value] = true;
    }

    /**
     * 解析默认值注解
     * @param string $value
     */
    protected function parseAnnotationDefault(string $value){
        $this->default = $value;
    }

    /**
     * 解析备注注解
     * @param string $value
     */
    protected function parseAnnotationComment(string $value){
        $this->comment = $value;
    }

    /**
     * 是否是ORM属性
     * @return bool
     */
    public function isSupport():bool {
        return $this->isSupport;
    }

    /**
     * 获取列名
     * @return string
     */
    public function getName():string {
        return $this->property->getName();
    }

    /**
     * 获取对应的列名
     * @return string
     */
    public function getColumnName():string {
        return $this->column;
    }

    /**
     * 获取字段类型
     * @return string
     */
    public function getColumnType():string {
        return $this->type;
    }

    /**
     * 判断是否为主键
     * @return bool
     */
    public function isPrimary():bool {
        if(isset($this->constraint['primary']))
            return $this->constraint['primary'];
        return false;
    }

    /**
     * 判断是否无符号
     * @return bool
     */
    public function isUnsigned():bool {
        if(isset($this->constraint['unsigned']))
            return $this->constraint['unsigned'];
        return false;
    }

    /**
     * 判断是否非空
     * @return bool
     */
    public function isNoNull():bool {
        if(isset($this->constraint['no-null']))
            return $this->constraint['no-null'];
        return false;
    }

    /**
     * 是否指定默认值
     * @return bool
     */
    public function hasDefault():bool {
        return is_string($this->default);
    }

    /**
     * 获取默认值
     * @return string
     */
    public function getDefault():string {
        return $this->default;
    }

    /**
     * 是否指定备注
     * @return bool
     */
    public function hasComment():bool {
        return is_string($this->comment);
    }

    /**
     * 获取备注值
     * @return string
     */
    public function getComment():string {
        return $this->comment;
    }

    /**
     * 属性值注入
     * @param $object
     * @param $value
     */
    public function injection($object, $value){
        $this->property->setAccessible(true);
        $this->property->setValue($object, $value);
        $this->property->setAccessible(false);
    }

    /**
     * 读取属性值
     * @param $object
     * @return mixed
     */
    public function read($object){
        $this->property->setAccessible(true);
        $value = $this->property->getValue($object);
        $this->property->setAccessible(false);
        return $value;
    }

}